package crudfx.util;

import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
import javax.swing.border.*;
import com.sun.javafx.runtime.Entry;
import com.sun.javafx.runtime.TypeInfo;
import com.sun.javafx.runtime.sequence.Sequence;
import com.sun.javafx.runtime.sequence.Sequences;
import java.awt.BorderLayout;
import java.lang.reflect.Method;
import javax.swing.JComponent;
import javafx.reflect.*;
import javafx.async.*;
import java.util.jar.*;
import java.net.*;
import java.io.*;

public class Tools {

    //public static Cursor handCursor = new Cursor(Cursor.HAND_CURSOR);
    //public static Object defaultComponents=null;
    static {
        //JEditorPane t=new JEditorPane("");
        //t.setDocument(null);
        System.out.println(getVersion());
    }

    public static String getVersion() {
        return "CRUDfx SDK v1.5.39";
    }

    public static String readText(InputStream stream, String encoding) {
        String s = "";
        //InputStream stream = this.getClass().getResourceAsStream(name);
        StringBuffer stringBuffer = new StringBuffer();
        int n = 0;
        try {
            InputStreamReader inputStreamReader;
            if (encoding == null) {
                inputStreamReader = new InputStreamReader(stream);
            } else {
                inputStreamReader = new InputStreamReader(stream, encoding);
            }
            while ((n = inputStreamReader.read()) != -1) {
                stringBuffer.append((char) n);
            }
            s = stringBuffer.toString();
            inputStreamReader.close();
            //stream.close();
        } catch (Throwable ex) {
            //MainMidlet.self.messageBox(ex.getMessage());
            ex.printStackTrace();
        }
        return s;
    }

    public static JFrame stage2Frame(javafx.stage.Stage stage) {
        JFrame f = null;
        try {
            com.sun.javafx.tk.swing.FrameStage fstage = (com.sun.javafx.tk.swing.FrameStage) stage.impl_getPeer();
            f = (JFrame) fstage.window;
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return f;
    }

    public static Set<Class<?>> getClasses(String packageName) throws Exception {
        //javafx.scene.Group g = new javafx.scene.Group();
        Tools g = new Tools();
        ClassLoader loader = g.getClass().getClassLoader();
        //Thread.currentThread().getContextClassLoader();
        return getClasses(loader, packageName);
    }

    public static Set<Class<?>> getClasses(ClassLoader loader, String packageName)
            throws Exception {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = loader.getResources(path);
        if (resources != null) {
            while (resources.hasMoreElements()) {
                String filePath = resources.nextElement().getFile();
                // WINDOWS HACK
                if (filePath.indexOf("%20") > 0) {
                    filePath = filePath.replaceAll("%20", " ");
                }
                if (filePath != null) {
                    if ((filePath.indexOf("!") > 0) & (filePath.indexOf(".jar") > 0)) {
                        String jarPath = filePath.substring(0, filePath.indexOf("!")).substring(filePath.indexOf(":") + 1);
                        // WINDOWS HACK
                        if (jarPath.indexOf(":") >= 0) {
                            jarPath = jarPath.substring(1);
                        }
                        classes.addAll(getFromJARFile(jarPath, path));
                    } else {
                        classes.addAll(
                                getFromDirectory(new File(filePath), packageName));
                    }
                }
            }
        }
        return classes;
    }

    static Set<Class<?>> getFromDirectory(File directory, String packageName) throws Exception {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        if (directory.exists()) {
            for (String file : directory.list()) {
                if (file.endsWith(".class")) {
                    System.out.println(file);
                    String name = packageName + '.' + file.replaceAll("\\.class", "");
                    //stripFilenameExtension(file);
                    Class<?> clazz = Class.forName(name);
                    classes.add(clazz);
                }
            }
        }
        return classes;
    }

    static Set<Class<?>> getFromJARFile(String jar, String packageName) throws Exception {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        JarInputStream jarFile = new JarInputStream(new FileInputStream(jar));
        JarEntry jarEntry;
        do {
            jarEntry = jarFile.getNextJarEntry();
            if (jarEntry != null) {
                String className = jarEntry.getName();
                if (className.endsWith(".class")) {
                    className = className.replaceAll("\\.class", "");
                    //stripFilenameExtension(className);
                    if (className.startsWith(packageName)) {
                        System.out.println(className);
                        //classes.add(Class.forName(className.replace('/', '.')));
                    }
                }
            }
        } while (jarEntry != null);
        return classes;
    }
    /*public static Class[] getClasses(String packageName)
    throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    java.util.List<File> dirs = new ArrayList<File>();
    while (resources.hasMoreElements()) {
    URL resource = resources.nextElement();
    dirs.add(new File(resource.getFile()));
    }
    ArrayList<Class> classes = new ArrayList<Class>();
    for (File directory : dirs) {
    classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
    }
    public static java.util.List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
    java.util.List<Class> classes = new ArrayList<Class>();
    if (!directory.exists()) {
    return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
    if (file.isDirectory()) {
    assert !file.getName().contains(".");
    classes.addAll(findClasses(file, packageName + "." + file.getName()));
    } else if (file.getName().endsWith(".class")) {
    classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
    }
    }
    return classes;
    }*/

    public static Dimension getFrameInnerSize(boolean menu) {
        Dimension d = new Dimension(0, 0);
        try {
            JFrame f = new JFrame();
            f.setSize(200, 200);
            f.setLocation(-300, 0);
            if (menu) {
                JMenu m = new JMenu("---");
                JMenuBar mb = new JMenuBar();
                mb.add(m);
                f.setJMenuBar(mb);
            }
            f.setVisible(true);
            //d = f.getRootPane().getSize();
            d = f.getContentPane().getSize();
            d.width = 200 - d.width;
            d.height = 200 - d.height;
            f.dispose();
        } catch (Throwable x) {
            x.printStackTrace();
        }
        return d;
    }

    public static JComponent fromScene(javafx.scene.Scene fxScene) {
        JComponent c = null;
        try {
            com.sun.javafx.tk.swing.SwingScene imp = (com.sun.javafx.tk.swing.SwingScene) fxScene.get$javafx$scene$Scene$impl_peer();
            c = imp.scenePanel;
            c.setOpaque(false);
            //System.out.println(c.getComponentCount());
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return c;
    }

    public static JComponent fromGroup(javafx.scene.Group g) {
        JComponent c = null;
        try {
            com.sun.scenario.scenegraph.SGGroup group = (com.sun.scenario.scenegraph.SGGroup) g.getPGGroup();
            group.getPanel();
            com.sun.scenario.scenegraph.JSGPanel panel = new com.sun.scenario.scenegraph.JSGPanel();
            panel.setScene(group);
            c = (JComponent) panel;
            c.setOpaque(false);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return c;
    }

    public static String i2s(int i) {
        return new String(new char[]{(char) i});
    }

    public static HTMLDocument getHTMLDocument(URL page) {
        HTMLEditorKit htmlKit = new HTMLEditorKit();
        HTMLDocument htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
        try {
            InputStream is = getStream(page);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            HTMLEditorKit.Parser parser = new ParserDelegator();
            HTMLEditorKit.ParserCallback callback = htmlDoc.getReader(0);
            parser.parse(br, callback, true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        //htmlDoc.setBase(page);
        //System.out.println("base is "+htmlDoc.getBase());
        return htmlDoc;
    }

    public static InputStream getStream(URL page) throws IOException {
        final URLConnection conn = page.openConnection();
        if (conn instanceof HttpURLConnection) {
            HttpURLConnection hconn = (HttpURLConnection) conn;
            hconn.setInstanceFollowRedirects(false);
            int response = hconn.getResponseCode();
            boolean redirect = (response >= 300 && response <= 399);
            if (redirect) {
                String loc = conn.getHeaderField("Location");
                if (loc.startsWith("http", 0)) {
                    page = new URL(loc);
                } else {
                    page = new URL(page, loc);
                }
                return getStream(page);
            }
        }
        return conn.getInputStream();
    }

    public static void dumpProperties() {
        Properties systemProperties = System.getProperties();
        for (Enumeration e = systemProperties.propertyNames(); e.hasMoreElements();) {
            String name = e.nextElement().toString();
            System.out.println(name + ": '" + System.getProperty(name) + "'");
        }
    }

    public static void logMessage(String x) {
        Date d = new Date();
        System.out.println(d.toString() + ": " + x);
    }

    public static void logException(Throwable x) {
        //Date d = new Date();
        //System.out.println(d.toString() + ": " + x.getMessage());
        logMessage(x.getMessage());
        x.printStackTrace();
    }

    public static boolean hasAlpha(Image image) {
        // If buffered image, the color model is readily available
        if (image instanceof BufferedImage) {
            BufferedImage bimage = (BufferedImage) image;
            return bimage.getColorModel().hasAlpha();
        }

        // Use a pixel grabber to retrieve the image's color model;
        // grabbing a single pixel is usually sufficient
        PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
        }

        // Get the image's color model
        ColorModel cm = pg.getColorModel();
        return cm.hasAlpha();
    }

    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        boolean hasAlpha = false;
        try {
            hasAlpha = hasAlpha(image);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
            if (hasAlpha) {
                transparency = Transparency.BITMASK;
            }

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

    public static void cacheImage(String url, String file, int w, int h) {
        try {
            javax.swing.ImageIcon image = new javax.swing.ImageIcon(new java.net.URL(url));
            if (image.getIconWidth() == w && image.getIconHeight() == h) {
                javax.imageio.ImageIO.write(crudfx.util.Tools.toBufferedImage(image.getImage()), "png", new java.io.File(file));
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static String getClipboardContents() {
        String result = "";
        try {
            java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            java.awt.datatransfer.Transferable contents = clipboard.getContents(null);
            boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(java.awt.datatransfer.DataFlavor.stringFlavor);
            if (hasTransferableText) {
                result = (String) contents.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor);
            }
        } catch (Throwable ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public static void setClipboardContents(String aString) {
        java.awt.datatransfer.StringSelection stringSelection = new java.awt.datatransfer.StringSelection(aString);
        java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(stringSelection, stringSelection);
    }
    /*public static String dumpStream(InputStream is){
    String r="";
    try{
    File file=File.createTempFile("stream", "file");
    BufferedReader br = new java.io.BufferedReader(
    new java.io.InputStreamReader(
    is));
    String inputLine;
    while((inputLine=br.readLine())!=null)System.out.println(inputLine);
    r=file.getAbsolutePath();
    }catch(Throwable t){
    t.printStackTrace();
    }
    return r;
    }*/

    /*public static void testMail() {
       MailTools.test();
    }*/

    public static boolean openURL(String url) {
        boolean result = false;
        String osName = System.getProperty("os.name");
        try {
            if (osName.startsWith("Mac OS")) {
                Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
                Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[]{String.class});
                openURL.invoke(null, new Object[]{url});
                result = true;
            } else {
                if (osName.startsWith("Windows")) {
                    Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
                    result = true;
                } else {
                    boolean found = false;
                    String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "seamonkey", "galeon", "kazehakase", "mozilla", "netscape"};
                    for (String browser : browsers) {
                        if (!found) {
                            found = Runtime.getRuntime().exec(new String[]{"which", browser}).waitFor() == 0;
                            if (found) {
                                Runtime.getRuntime().exec(new String[]{browser, url});
                            }
                            result = true;
                        }
                    }
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return result;
    }
}
